package com.zenithmind.mall.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.zenithmind.common.exception.BusinessException;
import com.zenithmind.mall.mapper.CouponMapper;
import com.zenithmind.mall.mapper.UserCouponMapper;
import com.zenithmind.mall.pojo.entity.Coupon;
import com.zenithmind.mall.pojo.entity.UserCoupon;
import com.zenithmind.mall.pojo.vo.CouponVO;
import com.zenithmind.mall.service.CouponUserService;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.BeanUtils;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.math.BigDecimal;
import java.time.LocalDateTime;
import java.util.List;
import java.util.stream.Collectors;

/**
 * 优惠券用户服务实现类 - 遵循单一职责原则，专门负责用户相关的优惠券操作
 * 
 * @author ZenithMind Team
 * @since 2025-07-03
 */
@Slf4j
@Service
@RequiredArgsConstructor
public class CouponUserServiceImpl implements CouponUserService {

    private final CouponMapper couponMapper;
    private final UserCouponMapper userCouponMapper;

    @Override
    public List<CouponVO> getAvailableCoupons(String userId, BigDecimal orderAmount) {
        // 查询用户可用的优惠券
        LambdaQueryWrapper<UserCoupon> userCouponWrapper = new LambdaQueryWrapper<>();
        userCouponWrapper.eq(UserCoupon::getUserId, userId)
                        .eq(UserCoupon::getStatus, 0) // 未使用
                        .eq(UserCoupon::getIsDeleted, 0);
        
        List<UserCoupon> userCoupons = userCouponMapper.selectList(userCouponWrapper);
        
        return userCoupons.stream()
                .map(userCoupon -> {
                    Coupon coupon = couponMapper.selectById(userCoupon.getCouponId());
                    if (coupon != null && coupon.canUseForAmount(orderAmount)) {
                        CouponVO vo = convertToVO(coupon);
                        vo.setUserCouponId(userCoupon.getId());
                        return vo;
                    }
                    return null;
                })
                .filter(vo -> vo != null)
                .collect(Collectors.toList());
    }

    @Override
    public List<CouponVO> getUserCoupons(String userId, Integer status) {
        LambdaQueryWrapper<UserCoupon> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(UserCoupon::getUserId, userId)
               .eq(status != null, UserCoupon::getStatus, status)
               .eq(UserCoupon::getIsDeleted, 0)
               .orderByDesc(UserCoupon::getCreateTime);
        
        List<UserCoupon> userCoupons = userCouponMapper.selectList(wrapper);
        
        return userCoupons.stream()
                .map(userCoupon -> {
                    Coupon coupon = couponMapper.selectById(userCoupon.getCouponId());
                    if (coupon != null) {
                        CouponVO vo = convertToVO(coupon);
                        vo.setUserCouponId(userCoupon.getId());
                        vo.setUserCouponStatus(userCoupon.getStatus());
                        vo.setReceiveTime(userCoupon.getCreateTime());
                        vo.setUseTime(userCoupon.getUseTime());
                        return vo;
                    }
                    return null;
                })
                .filter(vo -> vo != null)
                .collect(Collectors.toList());
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public Boolean receiveCoupon(String couponId, String userId) {
        // 检查优惠券是否存在且可领取
        Coupon coupon = couponMapper.selectById(couponId);
        if (coupon == null) {
            throw new BusinessException("优惠券不存在");
        }
        
        if (!coupon.canReceive()) {
            throw new BusinessException("优惠券不可领取");
        }
        
        // 检查用户是否可以领取
        if (!canReceiveCoupon(couponId, userId)) {
            throw new BusinessException("您已达到领取上限");
        }
        
        // 检查库存
        if (!coupon.hasStock()) {
            throw new BusinessException("优惠券已被抢完");
        }
        
        // 创建用户优惠券记录
        UserCoupon userCoupon = new UserCoupon();
        userCoupon.setUserId(userId);
        userCoupon.setCouponId(couponId);
        userCoupon.setStatus(0); // 未使用
        userCoupon.setCreateBy(userId);
        
        if (userCouponMapper.insert(userCoupon) <= 0) {
            throw new BusinessException("领取优惠券失败");
        }
        
        // 增加优惠券领取数量
        if (!coupon.increaseReceivedCount()) {
            throw new BusinessException("优惠券库存不足");
        }
        couponMapper.updateById(coupon);
        
        log.info("用户 {} 领取优惠券 {} 成功", userId, couponId);
        return true;
    }

    @Override
    public Boolean canReceiveCoupon(String couponId, String userId) {
        Coupon coupon = couponMapper.selectById(couponId);
        if (coupon == null || !coupon.canReceive()) {
            return false;
        }
        
        // 检查用户领取限制
        if (coupon.getLimitPerUser() != null && coupon.getLimitPerUser() > 0) {
            Integer receivedCount = getUserReceivedCount(couponId, userId);
            if (receivedCount >= coupon.getLimitPerUser()) {
                return false;
            }
        }
        
        return true;
    }

    @Override
    public Integer getUserReceivedCount(String couponId, String userId) {
        LambdaQueryWrapper<UserCoupon> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(UserCoupon::getUserId, userId)
               .eq(UserCoupon::getCouponId, couponId)
               .eq(UserCoupon::getIsDeleted, 0);
        
        return Math.toIntExact(userCouponMapper.selectCount(wrapper));
    }

    /**
     * 转换为VO
     */
    private CouponVO convertToVO(Coupon coupon) {
        CouponVO vo = new CouponVO();
        BeanUtils.copyProperties(coupon, vo);
        
        // 设置状态名称
        vo.setStatusName(getStatusName(coupon.getStatus()));
        vo.setTypeName(getTypeName(coupon.getType()));
        
        // 计算剩余数量
        if (coupon.getTotalCount() != null && coupon.getTotalCount() > 0) {
            int received = coupon.getReceivedCount() != null ? coupon.getReceivedCount() : 0;
            vo.setRemainingCount(Math.max(0, coupon.getTotalCount() - received));
        }
        
        // 检查是否过期
        if (coupon.getEndTime() != null) {
            vo.setExpired(LocalDateTime.now().isAfter(coupon.getEndTime()));
        }
        
        return vo;
    }

    private String getStatusName(Integer status) {
        if (status == null) return "未知";
        switch (status) {
            case 0: return "未开始";
            case 1: return "进行中";
            case 2: return "已结束";
            case 3: return "已停用";
            default: return "未知";
        }
    }

    private String getTypeName(Integer type) {
        if (type == null) return "未知";
        switch (type) {
            case 1: return "满减券";
            case 2: return "折扣券";
            case 3: return "免邮券";
            default: return "未知";
        }
    }
}
